<?php
#
# dmBridge: a data access framework for CONTENTdm(R)
#
# Copyright © 2009, 2010, 2011 Board of Regents of the Nevada System of Higher
# Education, on behalf of the University of Nevada, Las Vegas
#

/**
 * @author Alex Dolski <alex.dolski@unlv.edu>
 * @license http://www.opensource.org/licenses/mit-license.php
 */
class DMCPAdminController extends DMAbstractController {

	/**
	 * Array of key-value pairs to make accessible in the template
	 */
	protected $tpl_vars = array();

	/**
	 * @Override
	 */
	protected function authorize() {
		if (!$this->getUser()) {
			DMHTTPRequest::redirectToParams("admin/login");
			die;
		}
	}

	/**
	 * @throws DMFileAccessException
	 */
	public function preFlightCheck() {
		// don't want to call authorize() from self::login()
		$this->authorize();
		$path = DMConfigXML::getInstance()->getFullPath();
		if (!file_exists($path)) {
			throw new DMIOException(
				$path . ". " . DMLocalizedString::getString("CHECK_DATA_ROOT"));
		} else if (!is_readable(DMConfigXML::getInstance()->getFullPath())) {
			throw new DMIOException(sprintf(
					DMLocalizedString::getString("NOT_READABLE"), $path));
		} else if (!is_writable(DMConfigXML::getInstance()->getFullPath())) {
			throw new DMIOException(sprintf(
					DMLocalizedString::getString("NOT_WRITABLE"), $path));
		}
	}

	/**
	 * By default, redirects to the &quot;admin&quot; params. Override this by
	 * sending a &quot;dest_params&quot; key in POST data.
	 *
	 * @since 0.1
	 */
	public function login() {
		$user = $params = null;
		$req = $this->getHTTPRequest();
		if ($req->getMethod() == DMHTTPMethod::POST) {
			try {
				$rep = $req->getRepresentation();
				$user = new DMUser($rep->getFormValue("username"));
				$as = DMAuthenticationServiceFactory::getService();
				$result = $as->authenticate(
						$user, $rep->getFormValue("password"));
				if ($result) {
					$req->getSession()->setUser($user);
					$this->logSuccessfulLoginAttempt();
					$params = ($rep->getFormValue("dest_params"))
						? $rep->getFormValue("dest_params") : "admin";
					DMHTTPRequest::redirectToParams($params);
					$as->sendCookies();
					die;
				} else {
					$this->logFailedLoginAttempt();
					// mitigate brute-force attacks
					sleep(DMAbstractController::AUTHENTICATION_DELAY);
					header("HTTP/1.1 401 Unauthorized");
					$req->getSession()->setFlash(
							new DMFlash(
									DMLocalizedString::getString("LOGIN_FAILED"),
									false));
				}
			} catch (DMException $e) {
				$req->getSession()->setFlash(
						new DMFlash($e->getMessage(), false));
			}
		}

		$this->renderTemplate("/templates/admin/login.html.php");
		die;
	}

	/**
	 * If the user is logged in, logs out the user by erasing his/her
	 * serialized DMUser object from the session. If the user is not logged in,
	 * redirects to the login page.
	 *
	 * @since 0.1
	 */
	public function logout() {
		$as = DMAuthenticationServiceFactory::getService();
		$user = $this->getUser();
		if ($user) {
			$as->logout($user);
			$this->getSession()->setFlash(new DMFlash(
					DMLocalizedString::getString("LOGOUT_SUCCESS")));
			DMHTTPRequest::redirectToParams("admin/login");
		} else {
			DMHTTPRequest::redirectToParams("admin/login");
		}
		die;
	}

	private function logFailedLoginAttempt() {
		$this->logLoginAttempt(
			sprintf(
				DMLocalizedString::getString("LOGIN_FAILED_LOG_ENTRY"),
				$this->getHTTPRequest()->getRepresentation()->getFormValue("username")));
	}

	private function logSuccessfulLoginAttempt() {
		$this->logLoginAttempt(
			sprintf(
				DMLocalizedString::getString("LOGIN_SUCCEEDED_LOG_ENTRY"),
				$this->getHTTPRequest()->getRepresentation()->getFormValue("username")));
	}

	private function logLoginAttempt($msg) {
		$entry = new DMLogEntry($msg, 3);
		$logger = new DMLogger();
		$logger->log($entry);
	}

	public function main() {
		$this->preFlightCheck();
		$this->renderTemplate("/templates/admin/main.html.php");
		die;
	}

	/**
	 * Renders the module template at the given pathname. To pass variables
	 * into the template, add them to the <code>$tpl_vars</code> instance
	 * variable, which will be made available in the template as
	 * <code>$view</code>.
	 *
	 * @param string abs_pathname The absolute pathname of the template
	 */
	protected function renderModuleTemplate($abs_pathname) {
		$ts = new DMTemplateSet();
		$tpl = new DMTemplate($ts, "");
		$tpl->setAbsolutePathname($abs_pathname);
		$view = new DMControlPanelView($tpl, $this->getSession());
		$view->setTemplateVars($this->tpl_vars);
		include_once($abs_pathname);
	}

	/**
	 * Renders the template at the given pathname. To pass variables into the
	 * template, add them to the <code>$tpl_vars</code> instance variable,
	 * which will be made available in the template as <code>$view</code>.
	 *
	 * <strong>This method is not for use by modules.</strong> Modules should
	 * use <code>renderModuleTemplate()</code> instead.
	 *
	 * @param string pathname
	 */
	protected function renderTemplate($pathname) {
		$ts = new DMTemplateSet();
		$ts->setName("admin");
		$tpl = new DMTemplate($ts, $pathname);
		$view = new DMControlPanelView($tpl, $this->getSession());
		$view->setTemplateVars($this->tpl_vars);
		include_once($tpl->getAbsolutePathname());
	}

}
